package com.software.yh.config;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: lsy
 * @date: 2025/11/5
 * @version: 1.0
 */
@Aspect
@Component
public class GrpcLoggerFilter {
    private static final Logger log = LoggerFactory.getLogger(GrpcLoggerFilter.class);

    @Around("execution(* com.software.yh.service.grpc..*(..))") // 拦截 service 包下所有方法
    public Object grpcAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String canonicalName = method.getDeclaringClass().getCanonicalName();
        log.info("{}#{}, Request: {}", canonicalName, method.getName(),
                formatArgss(Arrays.stream(method.getParameters()).map(Parameter::getName).collect(Collectors.toList()), joinPoint.getArgs()));
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            result = joinPoint.proceed(); // 执行目标方法
            return result;
        } finally {
            // 打印出参和耗时
            log.info("{}#{} - 出参: {}, 耗时: {}ms", canonicalName, methodSignature.getMethod().getName(), formatResult(result), System.currentTimeMillis() - startTime);
        }
    }

    /**
     * 方法参数格式化
     * */
    private Object formatArgss(List<String> paramNames, Object[] args){
        if (args == null || args.length == 0) return "{}";
        StringBuilder sb = new StringBuilder("{");
        for (int i = 0; i < args.length; i++) {
            String paramName = paramNames != null && i < paramNames.size() ? paramNames.get(i) : "arg" + i;
            Object value = args[i];
            sb.append("\"").append(paramName).append("\":")
                    .append(value == null ? "null" : "\"" + value.toString().replace("\"", "\\\"") + "\"");
            if (i < args.length - 1) sb.append(", ");
        }
        sb.append("}");
        return sb.toString();
    }

    // 格式化返回值
    private String formatResult(Object result) {
        return result == null ? "null" : JSONObject.toJSONString(result);
    }

}
